package net;

import action.ActionRegistry;
import action.ActionRegistry.Action;
import action.ChangeCardItems;
import action.FairyBattle;
import action.FairyHistory;
import action.FloorRun;
import action.GetAreaInfo;
import action.GetFairyList;
import action.GetFloorInfo;
import action.GetNoNameList;
import action.LevelUp;
import action.Login;
import action.PVPRedirect;
import action.PvpWithNoName;
import action.ReturnMain;
import info.CardConfigInfo;
import info.FairyInfo;
import info.FloorInfo;
import info.NoNameInfo;

import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;

import start.Go;
import start.Info;
import start.Info.EventType;
import start.Think;

public class Process
{
  public static Connect connect;
  public static Info info;

  public Process()
  {
    connect = new Connect();
    info = new Info();
  }

  public static Document ParseXMLBytes(byte[] in) throws Exception
  {
    ByteArrayInputStream bais = null;
    try {
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();
      bais = new ByteArrayInputStream(in);
      return builder.parse(bais);
    }
    catch (Exception e) {
      throw e;
    }
  }

  public void start() {
    try {
      execute(Think.doIt(getPossibleAction()));
    } catch (Exception e) {
      if (e.getMessage() != null) {
        Go.log(e.getMessage());
        if (e.getMessage().contains("9000"))
          try {
            Thread.sleep(1000 * Info.sleepTime);
          } catch (InterruptedException e1) {
            Go.log(e1.getMessage());
          } finally {
            info.events.push(Info.EventType.cookieOutOfDate);
          }
        else
          info.events.push(Info.EventType.fairyAppear);
      }
      else {
        Go.log("服务器未响应");
        info.events.push(Info.EventType.fairyAppear);
      }
    }
  }

  private static List<ActionRegistry.Action> getPossibleAction()
  {
    ArrayList result = new ArrayList();
    if (info.events.size() != 0)
      switch (((Info.EventType)info.events.pop()).ordinal()) {
      case 1:
      case 2:
        result.add(ActionRegistry.Action.LOGIN);
        break;
      case 9:
        result.add(ActionRegistry.Action.PRIVATE_FAIRY_BATTLE);
        break;
      case 3:
        result.add(ActionRegistry.Action.GET_FLOOR_INFO);
        break;
      case 6:
        result.add(ActionRegistry.Action.GET_FAIRY_LIST);
        break;
      case 20:
        result.add(ActionRegistry.Action.GOTO_FLOOR);
        break;
      case 21:
        result.add(ActionRegistry.Action.LV_UP);
      case 23:
        result.add(ActionRegistry.Action.GET_NONAME_LIST);
        break;
      case 22:
        result.add(ActionRegistry.Action.PVP);
        break;
      case 24:
        result.add(ActionRegistry.Action.FAIRY_HISTORY);
      case 4:
      case 5:
      case 7:
      case 8:
      case 10:
      case 11:
      case 12:
      case 13:
      case 14:
      case 15:
      case 16:
      case 17:
      case 18:
      case 19: }  return result;
  }

  private void execute(ActionRegistry.Action action)
    throws Exception
  {
    int fairyLv;
    switch (action) {
    case CHANGE_CARD_ITEMS:
      try {
        if (Login.run()) {
          Go.log("cookie:" + info.cookie);
          Go.log("登陆成功，角色名：" + info.userName + ",等级：" + info.userLv + "，最大ap：" + info.apMax + "，当前ap：" + info.apCurrent + "，最大bc：" + info.bcMax + "，当前bc：" + info.bcCurrent + "，剩余属性点：" + info.freeApBcPoint);
          info.events.push(Info.EventType.fairyAppear);
        } else {
          info.events.push(Info.EventType.notLoggedIn);
        }
      } catch (Exception ex) {
        info.events.push(Info.EventType.notLoggedIn);
      }

    case GET_CARD_ITEM:
      if (info.freeApBcPoint > 0) {
        info.events.push(Info.EventType.levelUp);
      }
      else if (GetFairyList.run()) {
        info.events.push(Info.EventType.fairyHistory);
      } else {
        ReturnMain.run();

        if ((info.apCurrent >= info.floorCost) && (Info.isRun.equals("1")) && (info.bcCurrent < Info.stopRunWhenBcMore)) {
          Go.log("当前ap大于跑图所需ap,开始跑图");
          info.events.push(Info.EventType.needFloorInfo);
        }
        else if ((info.bcCurrent >= Info.whenBcMoreThan) && (Info.isPVP.equals("1"))) {
          Go.log("当前BC大于" + Info.whenBcMoreThan + ",进行点名操作");
          info.events.push(Info.EventType.getNoNameList);
        }
        else {
          Go.log("暂无妖精，" + Info.waitTime + "秒后重新获取列表");
          Thread.sleep(1000 * Info.waitTime);
          info.events.push(Info.EventType.fairyAppear);
        }
      }
      break;
    case LV_UP:
      if (info.freeApBcPoint > 0) {
        info.events.push(Info.EventType.levelUp);
      }
      else if (GetNoNameList.run()) {
        Go.log("寻找无名亚瑟完毕");
        info.events.push(Info.EventType.pvp);
      }
      break;
    case LOGIN:
      ChangeCardItems.run(Info.pvpCard, Info.pvpLr);
      for (NoNameInfo noName : info.noNameList)
      {
        if ((info.apCurrent >= info.floorCost) && (Info.isRun.equals("1")) && (info.bcCurrent < Info.stopRunWhenBcMore)) {
          Go.log("当前ap大于跑图所需ap,开始跑图");
          info.events.push(Info.EventType.needFloorInfo);
          break;
        }

        if (info.bcCurrent < Info.whenBcMoreThan) {
          Go.log("当前bc不足" + Info.whenBcMoreThan + "，停止点名");
          info.events.push(Info.EventType.fairyAppear);
          break;
        }
        if (PvpWithNoName.run(noName)) {
          if (info.isLvUp) {
            Go.log("升级了！");
            info.events.push(Info.EventType.levelUp);
            break;
          }
          Go.log("战斗结果：" + info.battleResult + "，获得经验：" + info.exp + "，金币：" + info.gold + "，剩余bc：" + info.bcCurrent + "，距离下次升级还需" + info.nextExp + "exp");
        }

        if (PVPRedirect.run()) {
          Go.log("刷新对战信息");
        }
        Go.log("等待战斗CD……");
        Thread.sleep(20000L);

        GetFairyList.run();
        for (FairyInfo fairyInfo : info.fairyInfos) {
          FairyHistory.run(fairyInfo);
        }
        if (info.canBattleFairyInfos.size() > 0) {
          info.events.push(Info.EventType.fairyCanBattle);
          break;
        }
        info.events.push(Info.EventType.getNoNameList);
      }
      break;
    case NOTHING:
      for (FairyInfo fairyInfo : info.fairyInfos) {
        FairyHistory.run(fairyInfo);
      }
      ReturnMain.run();
      if (info.canBattleFairyInfos.size() > 0) {
        info.events.push(Info.EventType.fairyCanBattle);
      }
      else if ((info.apCurrent >= info.floorCost) && (Info.isRun.equals("1")) && (info.bcCurrent < Info.stopRunWhenBcMore)) {
        Go.log("当前ap大于跑图所需ap,开始跑图");
        info.events.push(Info.EventType.needFloorInfo);
      }
      else if ((info.bcCurrent >= Info.whenBcMoreThan) && (Info.isPVP.equals("1"))) {
        Go.log("当前BC大于" + Info.whenBcMoreThan + ",进行点名操作");
        info.events.push(Info.EventType.getNoNameList);
      }
      else {
        Go.log("暂无妖精，" + Info.waitTime + "秒后重新获取列表");
        Thread.sleep(1000 * Info.waitTime);

        info.events.push(Info.EventType.fairyAppear);
      }break;
    case GET_FAIRY_LIST:
      Go.log("获取到妖精列表！共计" + info.canBattleFairyInfos.size() + "只");
      for (FairyInfo fairyInfo : info.canBattleFairyInfos) {
        BigDecimal i = BigDecimal.valueOf(fairyInfo.currentHp).divide(BigDecimal.valueOf(fairyInfo.maxHp), 2, 5);
        Go.log("用户：" + fairyInfo.userName + ",妖精：" + fairyInfo.name + ",等级：" + fairyInfo.lv + ",总血量：" + fairyInfo.maxHp + ",剩余血量：" + fairyInfo.currentHp);
        fairyLv = Integer.parseInt(fairyInfo.lv);
        ChangeCardItems.run(Info.wolf, Info.wolfLr);

        if (URLEncoder.encode(fairyInfo.name, "utf-8").contains("%E7%9A%84")) {
          for (CardConfigInfo cardConfigInfo : Info.cardConfigInfos)
            if ((fairyLv >= cardConfigInfo.lvMin) && (fairyLv <= cardConfigInfo.lvMax) && (info.bcCurrent >= cardConfigInfo.cardCost) && (i.doubleValue() >= cardConfigInfo.hp) && (cardConfigInfo.wake == 1)) {
              ChangeCardItems.run(cardConfigInfo.cardItem, cardConfigInfo.cardLr);
              break;
            }
        }
        else {
          for (CardConfigInfo cardConfigInfo : Info.cardConfigInfos) {
            if ((fairyLv >= cardConfigInfo.lvMin) && (fairyLv <= cardConfigInfo.lvMax) && (info.bcCurrent >= cardConfigInfo.cardCost) && (i.doubleValue() >= cardConfigInfo.hp) && (cardConfigInfo.wake == 0)) {
              ChangeCardItems.run(cardConfigInfo.cardItem, cardConfigInfo.cardLr);
              break;
            }
          }
        }
        if (FairyBattle.run(fairyInfo)) {
          if (info.isLvUp) {
            Go.log("升级了！");
            info.events.push(Info.EventType.levelUp);
            break;
          }
          Go.log("战斗结果：" + info.battleResult + "，获得经验：" + info.exp + "，金币：" + info.gold + "，剩余bc：" + info.bcCurrent + "，距离下次升级还需" + info.nextExp + "exp");
        }

        if (info.bcCurrent < 2) {
          Go.log("当前bc不足2，等待两分钟……");
          Thread.sleep(120000L);
        } else {
          Go.log("等待战斗CD……");
          Thread.sleep(20000L);
        }
      }

      info.canBattleFairyInfos = new ArrayList();
      info.events.push(Info.EventType.fairyAppear);
      break;
    case GUILD_TOP:
      if (LevelUp.run()) {
        info.isLvUp = false;
        info.freeApBcPoint = 0;
        Go.log("加点完毕");
        Go.log(info.userName + ",等级：" + info.userLv + "，最大ap：" + info.apMax + "，当前ap：" + info.apCurrent + "，最大bc：" + info.bcMax + "，当前bc：" + info.bcCurrent + "，剩余属性点：" + info.freeApBcPoint);
      }
      info.events.push(Info.EventType.fairyAppear);
      break;
    case EXPLORE:
      if (GetAreaInfo.run(false)) {
        FloorInfo floorInfo = null;
        boolean isClear = false;
        if (info.floorInfos.size() > 0) {
          if (Info.dayFirst.equals("1")) {
            floorInfo = (FloorInfo)info.floorInfos.get(info.floorInfos.size() - 1);
          }
          else if (Info.whatMap != 0) {
            GetAreaInfo.run(true);
            floorInfo = (FloorInfo)info.floorInfos.get(Info.whatMap - 1);
          } else {
            floorInfo = (FloorInfo)info.floorInfos.get(Info.whatMap);
          }

          GetFloorInfo.run(floorInfo, false);
        } else {
          GetAreaInfo.run(true);
          floorInfo = (FloorInfo)info.floorInfos.get(Info.whatMap);
          GetFloorInfo.run(floorInfo, true);
          isClear = true;
        }
        Go.log("获取地图完毕");
        if ((!info.floorId.equals("")) && (info.floorCost != 0))
          if (info.apCurrent < info.floorCost) {
            Go.log("ap不足");
            info.events.push(Info.EventType.fairyAppear);
          }
          else {
            while (FloorRun.run(floorInfo)) {
              Go.log(floorInfo.name + "，第" + info.floorId + "层，消耗ap" + info.floorCost + "，" + "获得经验：" + info.getExp + "，获得金币：" + info.runGold + "，地图进度：" + 
                info.progress + "%，事件类型：" + info.event_type + "，剩余ap：" + info.apCurrent + "，剩余bc：" + info.bcCurrent);

              if ((info.progress == 100) && (!isClear)) {
                info.floorId = info.nextFloorId;
                info.floorCost = info.nextFloorCost;
              }

              GetFairyList.run();
              for (FairyInfo fairyInfo : info.fairyInfos) {
                FairyHistory.run(fairyInfo);
              }
              if (info.canBattleFairyInfos.size() > 0) {
                info.events.push(Info.EventType.fairyCanBattle);
                break;
              }

              if ((info.areaClear == 1) && (!isClear)) {
                info.events.push(Info.EventType.needFloorInfo);
                break;
              }

              if (info.apCurrent < info.floorCost) {
                Go.log("ap不足");
                info.events.push(Info.EventType.fairyAppear);
                break;
              }

              if (info.bcCurrent > Info.stopRunWhenBcMore) {
                Go.log("bc超过设定值，停止跑图");
                info.events.push(Info.EventType.fairyAppear);
                break;
              }
            }
          }
      }
      else {
        info.events.push(Info.EventType.fairyAppear);
      }
      break;
    case FAIRY_HISTORY:
    case FAIRY_INFO:
    case GET_FAIRY_REWARD:
    case GET_FLOOR_INFO:
    case GET_NONAME_LIST:
    case GOTO_FLOOR:
    case GUILD_BATTLE:
    }
  }
}